package pers.whj.rpc.client;

import pers.whj.rpc.common.Config;
import pers.whj.rpc.protocol.Address;
import pers.whj.rpc.serialize.Decoder;
import pers.whj.rpc.serialize.DecoderImpl;
import pers.whj.rpc.serialize.Encoder;
import pers.whj.rpc.serialize.EncoderImpl;
import pers.whj.rpc.transport.TCPClient;
import pers.whj.rpc.transport.TransportClient;

import java.lang.reflect.Proxy;

/**
 * rpc客户端类，可以提供原有类的动态代理类
 */
public class Client {
    private Address serverAddress;
    private Encoder encoder;

    private Decoder decoder;
    private final TransportClient transportClient;

    public Client() {
        this.serverAddress = Config.SERVER_ADDRESS;
        this.encoder = new EncoderImpl();
        this.decoder = new DecoderImpl();
        this.transportClient = new TCPClient();
    }

    public Client(Address serverAddress) {
        this.serverAddress = serverAddress;
        this.encoder = new EncoderImpl();
        this.decoder = new DecoderImpl();
        this.transportClient = new TCPClient();
    }

    /**
     * 建立与服务器的连接
     *
     * @return 建立成功
     * @throws Exception 异常
     */
    public boolean connect() throws Exception {
        if (Config.DEBUG) {
            System.out.println("正连接服务器...");
        }
        this.transportClient.connect(serverAddress);
        return true;
    }

    /**
     * 断开与服务器的连接
     */
    public void close() {
        this.transportClient.close();
    }

    public void setServerAddress(Address serverAddress) {
        this.serverAddress = serverAddress;
    }

    public void setEncoder(Encoder encoder) {
        this.encoder = encoder;
    }

    public void setDecoder(Decoder decoder) {
        this.decoder = decoder;
    }

    /**
     * 获取目标类的动态代理类
     *
     * @param clazz 目标类
     * @param <T>   类型
     * @return 代理类对象
     */
    @SuppressWarnings({"unchecked"})
    public <T> T getProxy(Class<T> clazz) {
        Object obj = Proxy.newProxyInstance(
                getClass().getClassLoader(),
                new Class[]{clazz},
                new RemoteInvoker(clazz, this.encoder, this.decoder, this.transportClient)
        );
        if (Config.DEBUG) {
            System.out.println("获取目标类 " + clazz.getName() + " 的代理");
        }
        return (T) obj;
    }
}
